namespace SPDeploy
{
    using System;
    using System.IO;
    using Data;
    using Library;
    using Library.Exceptions;
    using Library.Helpers;
    using Library.Interfaces;
    using Library.Processing.Library;
    using Library.Processing.Processors;

    public class SPDeployCore
    {
        #region Methods: public

        public bool ProcessDeploymentConfiguration(string filename, ProcessorModes mode, int verbosity)
        {
            var logger = new ConsoleLogWriter {MinimumSeverity = LogSeverity.SubStep - verbosity};
            try
            {
                logger.Write(LogSeverity.Step, "Core", "Curre mode is " + mode);
                logger.Write(LogSeverity.Step, "Core", "Loading config file");
                Deployment config = LoadConfig(filename);
                ProcessorRegistry res = InitializeProcessorRegistry(logger);
                var configRunner = new DeploymentConfigRunner(res, new BredthFirstTraversalStrategy()) {LogWriter = logger};
                configRunner.Process(mode, config);
                logger.Write(LogSeverity.Step, "Core", "Completed Sucessfully");
                return true;
            }
            catch (DeploymentTargetConfigException e)
            {
                logger.Write(LogSeverity.Error, "Core", "{0}", e.Message);
            }
            catch (DeploymentTargetProcessorException e)
            {
                logger.Write(LogSeverity.Error, "Core", "{0}", e.Message);
            }
            catch (Exception e)
            {
                logger.Write(LogSeverity.Error, "Core", "{0}", e.Message);
                logger.Write(LogSeverity.Verbose, "Core", "{0}", e.StackTrace);
            }
            return false;
        }

        #endregion

        #region Methods: private

        private static ProcessorRegistry InitializeProcessorRegistry(ConsoleLogWriter logger)
        {
            logger.Write(LogSeverity.Verbose, "Core", "Initializing Processor Registry");
            var res = new ProcessorRegistry(logger, new ApplicationToProcessorSettingsWireUp(ProcessorSettings.Default));
            RegisterProcessors(res, logger);
            return res;
        }

        private Deployment LoadConfig(string filename)
        {
            var fileStream = new FileStream(filename, FileMode.Open);
            var provider = new DeploymentConfigXmlLoader();
            return provider.Load(fileStream);
        }

        private static void RegisterProcessors(IResolver<IDeploymentTargetProcessor> res, ConsoleLogWriter logger)
        {
            res.Register(new SolutionProcessor());
            res.Register(new SolutionDeploymentProcessor());
            res.Register(new FeatureActivationProcessor());
            res.Register(new WebApplicationProcessor());
            res.Register(new WebApplicationExtensionProcessor());
            res.Register(new SiteProcessor());
            res.Register(new WebProcessor());
            res.Register(new CentralAdminProcessor());
        }

        #endregion
    }
}